from flask import Flask,jsonify,request
app = Flask(__name__)

import time,re
import pandas as pd
import sys
import redis
import pickle
import logging
import hashlib
import configparser
import datetime
from sqlalchemy import create_engine, DateTime, String
import pymysql
import requests
import os
import pywencai
import akshare as ak
import pandas as pd
from datetime import datetime,timedelta
import traceback
pymysql.install_as_MySQLdb()

log_format = "%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s"
date_format = "%Y-%m-%d %H:%M:%S"  # 精确到秒
logging.basicConfig(level=logging.DEBUG, format=log_format, datefmt=date_format)

# 日志文件路径
log_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'application.log')

# 创建一个 handler，用于写入日志文件
file_handler = logging.FileHandler(log_file_path)
file_handler.setFormatter(logging.Formatter(log_format, date_format))
# 添加 handler 到 logger
logging.getLogger().addHandler(file_handler)

# 初始化配置解析器
config = configparser.ConfigParser()
current_dir = os.path.dirname(os.path.abspath(__file__))
config.read(current_dir+'/config.ini', encoding='utf-8')


# 获取Redis的配置信息
redis_host = config.get('Redis', 'host')
redis_port = config.getint('Redis', 'port')
redis_db = config.getint('Redis', 'db')
redis_password = config.get('Redis', 'password')
r = redis.Redis(host=redis_host, port=redis_port, db=redis_db, password=redis_password)

mysql_port = config.getint('mysql', 'port')
mysql_host = config.get('mysql', 'host')
mysql_db = config.get('mysql', 'db')
import urllib.parse
mysql_password = urllib.parse.quote(config.get('mysql', 'password'))
mysql_user = config.get('mysql', 'user')
db_url = f'mysql://{mysql_user}:{mysql_password}@{mysql_host}:{mysql_port}/{mysql_db}'

engine = create_engine(db_url,pool_size=20,max_overflow=20,pool_recycle=60)

def get_next_trade_date(trade_date):
    tool_trade_date_hist_sina_df = ak.tool_trade_date_hist_sina()
    # 筛选出所有晚于给定交易日的日期
    date_df = tool_trade_date_hist_sina_df[tool_trade_date_hist_sina_df["trade_date"] > pd.Timestamp(trade_date).date()]
    date_df = date_df.sort_values(by="trade_date", ascending=True)  # 按日期升序排序
    next_trade_date = date_df["trade_date"].values[0]  # 获取最接近给定日期的下一个交易日
    return next_trade_date.strftime("%Y-%m-%d")  # 格式化日期

def isCurrent(query_date):
    query_date = datetime.strptime(query_date, "%Y-%m-%d")
    current_datetime = datetime.now()
    current_date = current_datetime.date()
    # 比较传入的日期和当前日期


    if query_date.date() == current_date and current_datetime.hour <= 15 and current_datetime.hour >=9:
        return True
    else:
        return False


def add_remark(row):
    # 判断股票代码开头和对应条件
    if ((row['股票代码'].startswith('30') or row['股票代码'].startswith('68')) and row['change'] > 19.9):
        if row['hs_change'] > 3:
            return '20cm换手涨停'
        elif row['hs_change'] < 1:
            return '20cm一字板'
    elif ((row['股票代码'].startswith('00') or row['股票代码'].startswith('60')) and row['change'] > 9.88):
        if row['hs_change'] > 1:
            return '10cm换手涨停'
        elif row['hs_change'] < 1:
            return '10cm一字板'
    # 如果都不满足上述条件，则返回空值或其他默认值
    return ''

def add_suggestion(row):
    # 判断股票代码开头和对应条件
    # cdf = df[df['股票简称'] == stock_name]
    # print(row)
    # if row["股票简称"]==

    return ''

def get_pre_trade_date_n(trade_date,n):
    tool_trade_date_hist_sina_df = ak.tool_trade_date_hist_sina()
    date_df = tool_trade_date_hist_sina_df[tool_trade_date_hist_sina_df["trade_date"] < pd.Timestamp(trade_date).date()]
    date_df = date_df.sort_values(by="trade_date", ascending=False)
    pre_trade_date = date_df["trade_date"].values[n-1]
    return pre_trade_date.strftime("%Y%m%d")

def get_stock_rank_detail(stockName,conceptName,timestamp):
    # datetime_obj = datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S")
    # 将datetime对象格式化为"YYYYMMDD"格式的字符串
    formatted_date = timestamp.strftime("%Y-%m-%d")
    if isCurrent(formatted_date):
        table = "real_market_info_tdx"
    else:
        table = "real_market_info_tdx_h"

    formatted_date = timestamp.strftime("%Y%m%d")

    sql = f"select * from {table} rmd WHERE `timestamp`='{timestamp}'"

    stock_info_df = pickle.loads(r.get(f"stock_panqian:{formatted_date}"))
    # 从MySQL数据库中读取数据
    tdx_df = pd.read_sql(sql, engine)



    df = pd.merge(stock_info_df,tdx_df,how="inner",left_on="股票代码",right_on="code")

    df = df[df['所属概念'].str.contains(conceptName, regex=False)]
    df = df.sort_values(by="change",ascending=False)
    pd.set_option('display.max_columns', None)
    df["hs_change"] = round(100*(df["price"]-df["open"])/df["open"],2)
    df = df[["股票代码","股票简称","连续涨停天数","change","hs_change"]]

    # 应用函数并创建新列“备注”
    df['remark'] = df.apply(add_remark, axis=1)
    # df['suggestion'] = df.apply(add_suggestion, axis=1)

    suggestion = "没有可买的票"

    # 选股逻辑
    # 添加涨幅类型
    df['类型'] = df['股票代码'].apply(lambda x: '20cm' if x.startswith(('30', '68')) else '10cm')
    df['排名'] = df['change'].rank(method='dense', ascending=False)
    # df_filtered = df[df['remark'].apply(lambda x: '换手涨停' not in x)]


    cdf = df[df['股票简称']==stockName]


    stock_type = cdf["类型"].values[0]
    stock_rank = cdf["排名"].values[0]

    if stock_type == "20cm":
        if stock_rank == 1:
            suggestion = "板块20cm领涨，买"


    if stock_type == "10cm":
        if stock_rank == 1:
            suggestion = "板块10cm领涨，买"
        else:
            tdf = df.copy()
            tdf = tdf[~tdf['remark'].str.contains("20cm换手涨停", na=False)]
            tdf = tdf[~tdf['remark'].str.contains("一字板", na=False)]
            tdf = tdf[~tdf['类型'].str.contains("20cm", na=False)]
            tdf['排名'] = tdf['change'].rank(method='dense', ascending=False)
            ccdf = tdf[tdf['股票简称'] == stockName]
            print(stockName,ccdf)
            cc_stock_rank = ccdf["排名"].values[0]

            if cc_stock_rank==1:
                suggestion = "板块10cm换手领涨，买"


    df = df.head(10)
    res_dict = df.to_dict(orient="records")
    return res_dict,suggestion


def stock_rps(query_date):
    pre_20_day = get_pre_trade_date_n(query_date,20)
    sql = f'''
        SELECT 股票简称, MAX(`rps20`) AS rps
        FROM stock_rps
        WHERE trade_date >= '{pre_20_day}' and trade_date<='{query_date}'
        GROUP BY 股票简称;
        '''
    print(sql)
    df_rps = pd.read_sql(sql, engine)
    # stock_rps_list = df_rps["股票简称"].values
    # r.set("stock_rps",pickle.dumps(df_rps))
    return df_rps


@app.route('/sell_stock', methods=['POST'])
def sell_stock():
    data = request.json
    conceptName = data.get('conceptName')
    stock_name = data.get('stock_name')
    query_date = data.get('query_date')
    print(data)

    next_trade_day = get_next_trade_date(query_date)

    if isCurrent(next_trade_day):
        table = "real_market_info_tdx"
    else:
        table = "real_market_info_tdx_h"
    print(table)

    formatted_date = query_date.replace("-","")

    timestamp = f"{next_trade_day} 09:30:00"
    sql = f"select * from {table} rmd WHERE `timestamp`='{timestamp}'"
    print(sql)
    stock_info_df = pickle.loads(r.get(f"stock_panqian:{formatted_date}"))
    # 从MySQL数据库中读取数据
    tdx_df = pd.read_sql(sql, engine)

    df = pd.merge(stock_info_df,tdx_df,how="inner",left_on="股票代码",right_on="code")

    print(tdx_df)

    df = df[df['所属概念'].str.contains(conceptName, regex=False)]
    df = df.sort_values(by="change",ascending=False)
    df = df[["股票代码","股票简称","连续涨停天数","change"]]
    return jsonify(df.to_dict(orient="records"))




@app.route('/stock_detail', methods=['POST'])
def stock_detail():
    data = request.json
    timestamp = data.get('timestamp')
    conceptName = data.get('conceptName')

    print(timestamp)

    datetime_obj = datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S")
    # 将datetime对象格式化为"YYYYMMDD"格式的字符串
    formatted_date = datetime_obj.strftime("%Y-%m-%d")

    if isCurrent(formatted_date):
        table = "real_market_info_tdx"
    else:
        table = "real_market_info_tdx_h"

    formatted_date = datetime_obj.strftime("%Y%m%d")

    sql = f"select * from {table} rmd WHERE `timestamp`='{timestamp}'"
    print(sql)
    stock_info_df = pickle.loads(r.get(f"stock_panqian:{formatted_date}"))
    # 从MySQL数据库中读取数据
    tdx_df = pd.read_sql(sql, engine)



    df = pd.merge(stock_info_df,tdx_df,how="inner",left_on="股票代码",right_on="code")

    df = df[df['所属概念'].str.contains(conceptName, regex=False)]
    df = df.sort_values(by="change",ascending=False)
    pd.set_option('display.max_columns', None)
    df["hs_change"] = round(100*(df["price"]-df["open"])/df["open"],2)
    df = df[["股票代码","股票简称","连续涨停天数","change","hs_change"]]

    # 应用函数并创建新列“备注”
    df['remark'] = df.apply(add_remark, axis=1)
    df['suggestion'] = df.apply(add_suggestion, axis=1)

    df = df.head(10)
    return jsonify(df.to_dict(orient="records"))


def check_buy_stock(df):
    for index, row in df.iterrows():

        row["is20"] = False
        if row["股票代码"].startswith("30") or row["股票代码"].startswith("688"):
            row["is20"] = True

        # 买入时的判断参数
        if (row["change"] > 6
                and row["is20"] == False
                and row["change"] < 9
                and row["zhsl"] > 30
                and row["zhsl"] < 150
                and row["amount"] > 0.3
                and (row["bias5"] < 10 or row["bias5"] > 100)
                # and (stock_info["bias10"] < bais10 or stock_info["bias10"] > 100)
                and row["concept_rps_hs"] >= 99
                and row["market_value"] > 0
                and row["market_value"] < 9999
                and row["suggestion"] == '板块10cm领涨，买'
                and row["rps20"] < 99):
            return row

        if (row["change"] > 15
                and row["is20"] == True
                and row["change"] < 18
                and row["zhsl"] > 30
                and row["zhsl"] < 250
                and row["amount"] > 0.3
                and (row["bias5"] < 10 or row["bias5"] > 100)
                # and (stock_info["bias10"] < bais10 or stock_info["bias10"] > 100)
                and row["concept_rps_hs"] >= 99
                and row["market_value"] > 0
                and row["market_value"] < 9999
                and row["suggestion"] == '板块20cm领涨，买'
                and row["rps20"] < 99):
            return row

    return None

@app.route('/all', methods=['POST'])
def queryAll():
    data = request.json
    query_date = data.get('query_date')

    query_date_p = query_date.replace("-", "")
    stock_fupan_df = pickle.loads(r.get(f"stock_panqian:{query_date_p}"))

    # 比较传入的日期和当前日期
    if isCurrent(query_date):
        table = "analysis_stock_step"
    else:
        table = "analysis_stock_step"

    sql = f'''
         select * from {table} ass where date(`timestamp`)='{query_date}' and suggestion not like '%%不买%%'
    '''
    print(sql)
    df = pd.read_sql(sql, engine)
    df = pd.merge(stock_fupan_df, df, left_on='股票简称', right_on="name")


    # 按照'code'和'timestamp'排序，确保时间戳最早的记录在前
    df_sorted = df.sort_values(by=['股票简称', 'timestamp'])
    # 使用drop_duplicates去除重复的'code'，保留第一次出现的记录（即最早的记录）
    df = df_sorted.drop_duplicates(subset='股票简称', keep='first')
    df = df.sort_values(by="timestamp",ascending=False)
    df['timestamp'] = df['timestamp'].dt.strftime('%Y-%m-%d %H:%M:%S')
    df.fillna(0, inplace=True)
    res_dict = df.to_dict(orient="records")

    return jsonify(res_dict)

@app.route('/', methods=['POST'])
def main():

    data = request.json
    query_date = data.get('query_date')

    query_date_p = query_date.replace("-", "")
    stock_fupan_df = pickle.loads(r.get(f"stock_panqian:{query_date_p}"))

    # 比较传入的日期和当前日期
    if isCurrent(query_date):
        table = "analysis_stock_step"
    else:
        table = "analysis_stock_step"

    sql = f'''
         select * from {table} ass where date(`timestamp`)='{query_date}'
    '''

    print(sql)
    df = pd.read_sql(sql, engine)
    df = pd.merge(stock_fupan_df, df, left_on='股票简称', right_on="name")

    stock_list = df["name"].unique()
    buy_list = []

    for v in stock_list:
        df_stock = df[df["name"] == v]
        df_stock = df_stock.sort_values(by="timestamp", ascending=True)
        res = check_buy_stock(df_stock)
        if res is not None:
            buy_list.append(res)

    df = pd.DataFrame(buy_list)

    if len(df)==0:
        return []

    df.fillna(0, inplace=True)

    df = df.sort_values(by="timestamp",ascending=False)
    df['timestamp'] = df['timestamp'].dt.strftime('%Y-%m-%d %H:%M:%S')

    res_dict = df.to_dict(orient="records")

    return jsonify(res_dict)

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

